package com.yfyszk.kingbird.common.utils;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.URL;
import java.net.URLConnection;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
import java.util.SimpleTimeZone;
import java.util.TimeZone;

/**
 * 
* 类名称：DateUtils   
* 类描述：DateUtils工具类：提供一些日期通用处理的方法      
* 创建人：wgc   
* 创建时间：2017年3月31日 下午2:27:09   
*
 */
public class DateUtils {
	
	private static Logger logger = LoggerFactory.getLogger(DateUtils.class);
	
	/** 毫秒 */
	public static final long MS = 1;
	/** 每秒钟的毫秒数 */
	public static final long SECOND_MS = MS * 1000;
	/** 每分钟的毫秒数 */
	public static final long MINUTE_MS = SECOND_MS * 60;
	/** 每小时的毫秒数 */
	public static final long HOUR_MS = MINUTE_MS * 60;
	/** 每天的毫秒数 */
	public static final long DAY_MS = HOUR_MS * 24;
	/** 每月的毫秒数 */
	public static final long MONTH_MS = DAY_MS * 30;
	/** 每年的毫秒数 */
	public static final long YEAR_MS = MONTH_MS * 12;
 
	/** 标准日期（不含时间）格式化器 */
	public  static final String NORM_DATE_FORMAT = new String("yyyy-MM-dd");
	public  static final String YEAR_MONTH_DATE_FORMAT = new String("yyyy-MM");
	public  static final String TIME_STAMP = new String("yyyyMMdd");
	/** 标准日期时间格式化器 */
	public  static final String NORM_DATETIME_FORMAT = new String("yyyy-MM-dd HH:mm:ss");
	
	private DateUtils() {
		throw new AssertionError();
	}
	
	/**
	 * 当前时间，格式 yyyy-MM-dd HH:mm:ss
	 * @return 当前时间的标准形式字符串
	 */
	public static String now() {
		return formatDateTime(new Date());
	}
	public static String nowStr() {
		return nowStr(NORM_DATETIME_FORMAT);
	}
	public static String nowStr(String pattern) {
		return DateFormatUtils.format(getCalendar(), pattern);
	}
	public static Calendar getCalendar() {
		return Calendar.getInstance();
	}
	public static String nowDayTimeStamp() {
		return nowStr(TIME_STAMP);
	}
	/**
	 * 格式 yyyy-MM-dd HH:mm:ss
	 * @param date 被格式化的日期
	 * @return 格式化后的日期
	 */
	public static String formatDateTime(Date date) {
		return new SimpleDateFormat(NORM_DATETIME_FORMAT).format(date);
	}

	/**
	 * 当前日期，格式 yyyy-MM-dd
	 * @return 当前日期的标准形式字符串
	 */
	public static String today() {
		return formatDate(new Date());
	}

	/**
	 * 根据特定格式格式化日期
	 * @param date 被格式化的日期
	 * @param format 格式
	 * @return 格式化后的字符串
	 */
	public static String format(Date date, String format) {
		return new SimpleDateFormat(format).format(date);
	}

	/**
	 * 格式 yyyy-MM-dd 
	 * @param date 被格式化的日期
	 * @return 格式化后的字符串
	 */
	public static String formatDate(Date date) {
		return new SimpleDateFormat(NORM_DATE_FORMAT).format(date);
	}
	public static String nowDayStr() {
		return nowStr(NORM_DATE_FORMAT);
	}
 
	/**
	 * 将特定格式的日期转换为Date对象
	 * @param dateString 特定格式的日期
	 * @param format 格式，例如yyyy-MM-dd
	 * @return 日期对象
	 */
	public static Date parse(String dateString, String format) {
		try {
			return (new SimpleDateFormat(format)).parse(dateString);
		} catch (ParseException e) {
			logger.error("Parse" + dateString + " with format " + format + " error!", e);
		}
		return null;
	}

	/**
	 * 格式yyyy-MM-dd HH:mm:ss
	 * @param dateString 标准形式的时间字符串
	 * @return 日期对象
	 */
	public static Date parseDateTime(String dateString) {
		try {
			return new SimpleDateFormat(NORM_DATETIME_FORMAT).parse(dateString);
		} catch (ParseException e) {
			logger.error("Parse " + dateString + " with format "
					+ new SimpleDateFormat(NORM_DATETIME_FORMAT).toPattern() + " error!", e);
		}
		return null;
	}

	/**
	 * 格式yyyy-MM-dd
	 * @param dateString  标准形式的日期字符串
	 * @return  标准形式的日期字符串
	 */
	public static Date parseDate(String dateString) {
		try {
			return new SimpleDateFormat(NORM_DATE_FORMAT).parse(dateString);
		} catch (ParseException e) {
			logger.error("Parse " + dateString + " with format " + new SimpleDateFormat(NORM_DATE_FORMAT).toPattern()
					+ " error!", e);
		}
		return null;
	}

	/**
	 * 获取指定日期偏移指定时间后的时间
	 * @param date 基准日期
	 * @param calendarField 偏移的粒度大小（小时、天、月等）使用Calendar中的常数
	 * @param offsite 偏移量，正数为向后偏移，负数为向前偏移
	 * @return 偏移后的日期
	 * 
	 */
	public static Date getOffsiteDate(Date date, int calendarField, int offsite) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(calendarField, offsite);
		return cal.getTime();
	}

	/**
	 * 判断两个日期相差的时长<br/>(列：1年前7月25日)
	 * 返回 minuend - subtrahend 的差
	 * @param subtrahend 减数日期
	 * @param minuend 被减数日期
	 * @return 日期差
	 */
	public static String dateDiff(Date subtrahend, Date minuend) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(subtrahend);
		long diff = minuend.getTime() - subtrahend.getTime();
		if (diff <= HOUR_MS)
			return diff / MINUTE_MS + "分钟前";
		else if (diff <= DAY_MS)
			return diff / HOUR_MS + "小时" + (diff % HOUR_MS / MINUTE_MS) + "分钟前";
		else if (diff <= DAY_MS * 2)
			return "昨天" + calendar.get(Calendar.HOUR_OF_DAY) + "点" + calendar.get(Calendar.MINUTE) + "分";
		else if (diff <= DAY_MS * 3)
			return "前天" + calendar.get(Calendar.HOUR_OF_DAY) + "点" + calendar.get(Calendar.MINUTE) + "分";
		else if (diff <= MONTH_MS)
			return diff / DAY_MS + "天前" + calendar.get(Calendar.HOUR_OF_DAY) + "点" + calendar.get(Calendar.MINUTE)
					+ "分";
		else if (diff <= YEAR_MS)
			return diff / MONTH_MS + "个月" + (diff % MONTH_MS) / DAY_MS + "天前" + calendar.get(Calendar.HOUR_OF_DAY) + "点"
					+ calendar.get(Calendar.MINUTE) + "分";
		else
			return diff / YEAR_MS + "年前" + (calendar.get(Calendar.MONTH) + 1) + "月" + calendar.get(Calendar.DATE) + "日";
	}
	
	/**
	 * 距离截止日期还有多长时间
	 * @param date
	 * @return
	 */
	public static String fromDeadline(Date date) {
		long deadline = date.getTime();
		long now = new Date().getTime();
		long remain = deadline - now;
		if (remain <= HOUR_MS)
			return "只剩下" + remain / MINUTE_MS + "分钟";
		else if (remain <= DAY_MS)
			return "只剩下" + remain / HOUR_MS + "小时" + (remain % HOUR_MS / MINUTE_MS) + "分钟";
		else {
			long day = remain / DAY_MS;
			long hour = remain % DAY_MS / HOUR_MS;
			long minute = remain % DAY_MS % HOUR_MS / MINUTE_MS;
			return "只剩下" + day + "天" + hour + "小时" + minute + "分钟";
		}
	}
	
	/**
	 * 判断字符串是否是日期格式
	 * @param str 日期字符串
	 * @param format 日期格式，可以传空，默认使用"yyyy-MM-dd"格式
	 * @return
	 * @author zhangyu
	 * @date 2018年8月8日 下午2:57:00
	 */
	public static boolean isValidDate(String str, String format) {
		boolean convertSuccess = true;
		if(StringUtils.isBlank(format)){
			format = NORM_DATE_FORMAT;
		}
		// 指定日期格式
		SimpleDateFormat sdf = new SimpleDateFormat(format);
		try {
			// 设置lenient为false.
			// 否则SimpleDateFormat会比较宽松地验证日期，比如2007/02/29会被接受，并转换成2007/03/01
			sdf.setLenient(false);
			sdf.parse(str);
		} catch (ParseException e) {
			// e.printStackTrace();
			// 如果throw java.text.ParseException或者NullPointerException，就说明格式不对
			convertSuccess = false;
		}
		return convertSuccess;
	}
	/**
	 * 日期比较大小
	 * @param dateOne
	 * @param dateTwo
	 * @param dateFormatType
	 * @return dateOne >dateTwo 返回1  dateOne<dateTwo 返回-1
	 */
	public static int compareTime(String dateOne, String dateTwo , String dateFormatType){
	      
	    DateFormat df = new SimpleDateFormat(dateFormatType);
	    Calendar calendarStart = Calendar.getInstance();
	    Calendar calendarEnd = Calendar.getInstance();
	      
	    try {  
	        calendarStart.setTime(df.parse(dateOne));  
	        calendarEnd.setTime(df.parse(dateTwo));  
	    } catch (ParseException e) {
	        e.printStackTrace();  
	        return 100;  
	    }  
	  
	    int result = calendarStart.compareTo(calendarEnd);  
	    if(result > 0){  
	        result = 1;  
	    }else if(result < 0){  
	        result = -1;  
	    }else{  
	        result = 0 ;  
	    }  
	    return result ;  
	}  
	/** 
     * @param oldTime 较小的时间 
     * @param newTime 较大的时间 (如果为空   默认当前时间 ,表示和当前时间相比) 
     * @return -1 ：同一天.    0：昨天 .   1 ：至少是前天. 
     */
	public static  int isYesterday(Date oldTime, Date newTime) throws Exception {
        if(newTime==null){  
            newTime=new Date();
        }  
        //将下面的 理解成  yyyy-MM-dd 00：00：00 更好理解点  
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        String todayStr = format.format(newTime);
        Date today = format.parse(todayStr);
        //昨天 86400000=24*60*60*1000 一天  
        if((today.getTime()-oldTime.getTime())>0 && (today.getTime()-oldTime.getTime())<=86400000) {  
            return 0;  
        }  
        else if((today.getTime()-oldTime.getTime())<=0){ //至少是今天  
            return -1;  
        }  
        else{ //至少是前天  
            return 1;  
        }  
          
    }

	/*
	 * @Author hanzeyu
	 * @Description 获取指定时区的时间 东八区为:8
	 * @Date 2019/11/11 11:54
	 * @Param [timeZoneOffset,type]
	 * @return java.lang.String
	 **/
	public static Date getFormatedDateString(float timeZoneOffset) {

		if (timeZoneOffset > 13 || timeZoneOffset < -12) {
			timeZoneOffset = 0;
		}

		int newTime=(int)(timeZoneOffset * 60 * 60 * 1000);
		TimeZone timeZone;
		String[] ids = TimeZone.getAvailableIDs(newTime);
		if (ids.length == 0) {
			timeZone = TimeZone.getDefault();
		} else {
			timeZone = new SimpleTimeZone(newTime, ids[0]);
		}

		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		sdf.setTimeZone(timeZone);
		Date d= null;
		try {
			d = sdf.parse(sdf.format(new Date()));
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return d;
	}
	/**
	 * 网址访问
	 * 网址 获取北京时间
	 * @return urlDate 对象网址时间
	 */
	public static String getBjTime(){
		String url = "http://time.tianqi.com";  //北京时间
		String urlDate = null;
		try {
			URL url1 = new URL(url);
			URLConnection conn = url1.openConnection();  //生成连接对象
			conn.connect();  //连接对象网页
			Date date = new Date(conn.getDate());  //获取对象网址时间
			SimpleDateFormat df = new SimpleDateFormat(NORM_DATETIME_FORMAT);  //设置日期格式
			urlDate = df.format(date);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return urlDate;
	}
	/**
	 * 获取时间当前日期
	 * @return LocalDate
	 */
	public static LocalDate getLocalDate(){
		return LocalDate.now();
	}
public static void main(String[] args){
	System.out.println(getLocalDate());
}
	/**
	 * 获取当前时间
	 * @return LocalDateTime
	 */
	public static LocalDateTime getLocalDateTime(){
		return LocalDateTime.now();
	}

	/**
	 * 获取当前时间毫秒数
	 * @return Long
	 */
	public static Long getDateTimeStamp(){
		return LocalDateTime.now().atZone(ZoneId.of("Asia/Shanghai")).toInstant().toEpochMilli();
	}

	/**
	 * 获取Date类型当前时间
	 * @return Date
	 */
	public static Date getDateTime(){
		ZoneId zoneId = ZoneId.systemDefault();
		ZonedDateTime zonedDateTime = LocalDateTime.now().atZone(zoneId);
		Date dateTime = Date.from(zonedDateTime.toInstant());
		return dateTime;
	}

	/**
	 *获取Date类型当前日期
	 * @return Date
	 */
	public static Date getDate(){
		ZoneId zoneId = ZoneId.systemDefault();
		ZonedDateTime zonedDateTime = LocalDate.now().atStartOfDay(zoneId);
		Date date = Date.from(zonedDateTime.toInstant());
		return date;
	}
	/**
	 * 利用DateTimeFormatter类自带的格式定义日期时间
	 * @param date
	 * @param formatter
	 * @return
	 */
	public static LocalDate formatter(String date, DateTimeFormatter formatter){
		return LocalDate.parse(date,formatter);
	}

	/**
	 * 自定义格式日期时间
	 * DateTimeFormatter.ofPattern第二个参数也可以指定地域，有需要可以自己封装
	 * @param date
	 * @param formatter
	 * @return
	 */
	public static LocalDate formatter(String date,String formatter){
		DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(formatter);
		return LocalDate.parse(date,dateTimeFormatter);
	}

}
